

#ifndef BSP_ARCH_ARMV8
#define BSP_ARCH_ARMV8

#include <stdint.h>
#include "ft_types.h"

/* CurrentEL, Current Exception Level */
#define CURRENT_EL_MASK 0x3
#define CURRENT_EL_SHIFT 2

/* DAIF, Interrupt Mask Bits */
#define DAIF_DBG_BIT (1 << 3) /* Debug mask bit */
#define DAIF_ABT_BIT (1 << 2) /* Asynchronous abort mask bit */
#define DAIF_IRQ_BIT (1 << 1) /* IRQ mask bit */
#define DAIF_FIQ_BIT (1 << 0) /* FIQ mask bit */

/*
 * Interrupt flags
 */
#define AARCH64_DAIF_FIQ (1) /* FIQ */
#define AARCH64_DAIF_IRQ (2) /* IRQ */

/* Timer */
#define CNTV_CTL_ENABLE (1 << 0)  /* Enables the timer */
#define CNTV_CTL_IMASK (1 << 1)	  /* Timer interrupt mask bit */
#define CNTV_CTL_ISTATUS (1 << 2) /* The status of the timer interrupt. This bit is read-only */

//
// AArch64 SPSR
//
#define AARCH64_SPSR_EL3h 0b1101
#define AARCH64_SPSR_EL3t 0b1100
#define AARCH64_SPSR_EL2h 0b1001
#define AARCH64_SPSR_EL2t 0b1000
#define AARCH64_SPSR_EL1h 0b0101
#define AARCH64_SPSR_EL1t 0b0100
#define AARCH64_SPSR_EL0t 0b0000
#define AARCH64_SPSR_RW (1 << 4)
#define AARCH64_SPSR_F (1 << 6)
#define AARCH64_SPSR_I (1 << 7)
#define AARCH64_SPSR_A (1 << 8)
#define AARCH64_SPSR_D (1 << 9)
#define AARCH64_SPSR_IL (1 << 20)
#define AARCH64_SPSR_SS (1 << 21)
#define AARCH64_SPSR_V (1 << 28)
#define AARCH64_SPSR_C (1 << 29)
#define AARCH64_SPSR_Z (1 << 30)
#define AARCH64_SPSR_N (1 << 31)

//
// Multiprocessor Affinity Register
//
#define MPIDR_EL1_AFF3_LSB 32
#define MPIDR_EL1_U (1 << 30)
#define MPIDR_EL1_MT (1 << 24)
#define MPIDR_EL1_AFF2_LSB 16
#define MPIDR_EL1_AFF1_LSB 8
#define MPIDR_EL1_AFF0_LSB 0
#define MPIDR_EL1_AFF_WIDTH 8

//
// Data Cache Zero ID Register
//
#define DCZID_EL0_BS_LSB 0
#define DCZID_EL0_BS_WIDTH 4
#define DCZID_EL0_DZP_LSB 5
#define DCZID_EL0_DZP (1 << 5)

//
// System Control Register
//
#define SCTLR_EL1_UCI (1 << 26)
#define SCTLR_ELx_EE (1 << 25)
#define SCTLR_EL1_E0E (1 << 24)
#define SCTLR_ELx_WXN (1 << 19)
#define SCTLR_EL1_nTWE (1 << 18)
#define SCTLR_EL1_nTWI (1 << 16)
#define SCTLR_EL1_UCT (1 << 15)
#define SCTLR_EL1_DZE (1 << 14)
#define SCTLR_ELx_I (1 << 12)
#define SCTLR_EL1_UMA (1 << 9)
#define SCTLR_EL1_SED (1 << 8)
#define SCTLR_EL1_ITD (1 << 7)
#define SCTLR_EL1_THEE (1 << 6)
#define SCTLR_EL1_CP15BEN (1 << 5)
#define SCTLR_EL1_SA0 (1 << 4)
#define SCTLR_ELx_SA (1 << 3)
#define SCTLR_ELx_C (1 << 2)
#define SCTLR_ELx_A (1 << 1)
#define SCTLR_ELx_M (1 << 0)

//
// Architectural Feature Access Control Register
//
#define CPACR_EL1_TTA (1 << 28)
#define CPACR_EL1_FPEN (3 << 20)

//
// Architectural Feature Trap Register
//
#define CPTR_ELx_TCPAC (1 << 31)
#define CPTR_ELx_TTA (1 << 20)
#define CPTR_ELx_TFP (1 << 10)

//
// Secure Configuration Register
//
#define SCR_EL3_TWE (1 << 13)
#define SCR_EL3_TWI (1 << 12)
#define SCR_EL3_ST (1 << 11)
#define SCR_EL3_RW (1 << 10)
#define SCR_EL3_SIF (1 << 9)
#define SCR_EL3_HCE (1 << 8)
#define SCR_EL3_SMD (1 << 7)
#define SCR_EL3_EA (1 << 3)
#define SCR_EL3_FIQ (1 << 2)
#define SCR_EL3_IRQ (1 << 1)
#define SCR_EL3_NS (1 << 0)

//
// Hypervisor Configuration Register
//
#define HCR_EL2_ID (1 << 33)
#define HCR_EL2_CD (1 << 32)
#define HCR_EL2_RW (1 << 31)
#define HCR_EL2_TRVM (1 << 30)
#define HCR_EL2_HVC (1 << 29)
#define HCR_EL2_TDZ (1 << 28)

#define INTERRUPT_ENABLE() __asm__ __volatile__("msr daifclr, #2" :: \
													: "memory")

#define INTERRUPT_DISABLE() __asm__ __volatile__("msr daifset, #2" :: \
													 : "memory")

#define MODE_EL_SHIFT (0x2)
#define MODE_EL_MASK (0x3)

#define MODE_EL3 (0x3)
#define MODE_EL2 (0x2)
#define MODE_EL1 (0x1)
#define MODE_EL0 (0x0)

#define GET_EL(_mode) (((_mode) >> MODE_EL_SHIFT) & MODE_EL_MASK)

/* memory synchronization operations */

/* Instruction Synchronization Barrier */
#define ISB() __asm__ __volatile__("isb sy")

/* Data Synchronization Barrier */
#define DSB() __asm__ __volatile__("dsb sy")

/* Data Memory Barrier */
#define DMB() __asm__ __volatile__("dmb sy")

/* Wait For Interrupt */
#define wfi() asm volatile("wfi" \
						   :     \
						   :     \
						   : "memory")

/* Count leading zeroes (clz) */
#define clz(arg) (            \
	{                         \
		uint32_t rval;        \
		__asm__ __volatile__( \
			"clz	%0,%1"       \
			: "=r"(rval)      \
			: "r"(arg));      \
		rval;                 \
	})

#define MTCPDC(reg, val) __asm__ __volatile__("dc " #reg ",%0" \
											  :                \
											  : "r"(val))
#define MTCPIC(reg, val) __asm__ __volatile__("ic " #reg ",%0" \
											  :                \
											  : "r"(val))

#define MTCPICALL(reg) __asm__ __volatile__("ic " #reg)
#define MTCPTLBI(reg) __asm__ __volatile__("tlbi " #reg)
#define MTCPAT(reg, val) __asm__ __volatile__("at " #reg ",%0" \
											  :                \
											  : "r"(val))

#define AARCH64_READ_SYSREG(reg) (          \
	{                                       \
		uint64_t val;                       \
		__asm__ __volatile__("mrs %0," #reg \
							 : "=r"(val));  \
		val;                                \
	})
#define AARCH64_WRITE_SYSREG(reg, val) __asm__ __volatile__("msr " #reg ", %0\n\tdsb sy\n\tisb" ::"r"(val));

/* PSTATE and special purpose register access functions */
uint32_t raw_read_current_el(void);
uint32_t get_current_el(void);
uint32_t raw_read_daif(void);
void raw_write_daif(uint32_t daif);
void enable_debug_exceptions(void);
void enable_serror_exceptions(void);
void enable_irq(void);
void enable_fiq(void);
void disable_debug_exceptions(void);
void disable_serror_exceptions(void);
void disable_irq(void);
void disable_fiq(void);
/* SPSR_EL1, Saved Program Status Register (EL1) */
uint32_t raw_read_spsr_el1(void);
void raw_write_spsr_el1(uint32_t spsr_el1);
/* ISR_EL1, Interrupt Status Register */
uint32_t raw_read_isr_el1(void);
uint64_t raw_read_rvbar_el1(void);
void raw_write_rvbar_el1(uint64_t rvbar_el1);
uint64_t raw_read_vbar_el1(void);
void raw_write_vbar_el1(uint64_t vbar_el1);

/* CNTV_CTL_EL0, Counter-timer Virtual Timer Control register */
uint32_t raw_read_cntv_ctl(void);
void disable_cntv(void);
void enable_cntv(void);
/* CNTFRQ_EL0, Counter-timer Frequency register */
uint32_t raw_read_cntfrq_el0(void);
void raw_write_cntfrq_el0(uint32_t cntfrq_el0);
/* CNTVCT_EL0, Counter-timer Virtual Count register */
uint64_t raw_read_cntvct_el0(void);
/* CNTV_CVAL_EL0, Counter-timer Virtual Timer CompareValue register */
uint64_t raw_read_cntv_cval_el0(void);
void raw_write_cntv_cval_el0(uint64_t cntv_cval_el0);

u64 get_hcr_el2(void);
u32 get_esr_el1(void);
#endif // V8_SYSTEM_H
